package com.example.demo.aop;

import com.example.demo.entity.Idempotent;
import com.example.demo.service.IdempotentService;
import org.apache.commons.collections4.MapUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

@Aspect
@Component
public class IdempotentAspect {
    @Autowired
    private IdempotentService idempotentService;

    @Before("@annotation(Idempotents)")
    public boolean isIdempotent(JoinPoint joinPoint) throws NoSuchAlgorithmException, UnsupportedEncodingException, UndeclaredThrowableException {
        Object[] args = joinPoint.getArgs();
        Object object = args.length > 0 ? args[0] : null;
        if (object instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) object;
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (MapUtils.isNotEmpty(parameterMap)) {
                StringBuilder str = new StringBuilder();
                parameterMap.forEach((name, value) -> {
                    String formatStr = String.format("%s = %s", name, Arrays.toString(value));
                    str.append(formatStr);
                });
                if (str.length() > 0
                        && !"null".equals(str.toString())
                        && !"".equals(str.toString())) {
                    MessageDigest md = MessageDigest.getInstance("MD5");
                    byte[] digest = md.digest(str.toString().getBytes("UTF-8"));
                    StringBuilder md5Builder = new StringBuilder();
                    for (byte b : digest) {
                        md5Builder.append(String.format("%02x", b & 0xff));
                    }
                    String md5Value = md5Builder.toString();
                    Idempotent idempotent = Idempotent.builder()
                            .setTenantId(10005L)
                            .setCreatedAt(new Date(System.currentTimeMillis()))
                            .setLastModifiedAt(new Date(System.currentTimeMillis()))
                            .setParamMd5(md5Value)
                            .build();
                    idempotentService.insert(idempotent);
                }
            }
        }
        return true;
    }
}
